/**
 * @brief 2.3.3 理解复合类型的声明
 * 
 * 
 * @param argc 
 * @param argv 
 * @return int 
 */
int main(int argc, char const *argv[])
{
    int* p; // 合法，但容易产生误会
    int* p1, p2; // p1是指向int的指针，p2是int
    int *p3, *p4; // p3和p4都是指向int的指针，
    
    // 把修饰符（*）和变量标识符（p3、p4）写在一起，如：*p3，这种形式强调变量具有的复合类型
    // 把修饰符（*）和类型名（int）写在一起，如：int* p3，这种形式强调本次声明定义了一种复合类型

    // 指针的指针
    // 指针是内存中的对象，像其他对象一样也有自己的地址，因此允许把指针的地址存放在另一个指针当中。
    // 例如：**表示指针的指针，***表示指针的指针的指针，以此类推。
    int iVal = 1024;
    int *pi = &iVal;
    int **ppi = &pi; // ppi指向一个int型的指针
    // 解引用int型指针会得到一个int型的数，同样，解引用指向指针的指针会得到一个指针。

    // 指向指针的引用
    // 引用本身不是一个对象，因此不能定义指向引用的指针。但指针是对象，所以存在对指针的引用
    int i = 42;
    int *p;
    int *&r = p; // r是一个对指针p的引用，写成int* &r = p;是不是更好理解一些？
    r = &i; // r引用了一个指针，因此给r赋值&i就是令p指向i
    *r = 0; // 解引用r得到i，也就是p指向的对象，将i的值改为0
    

    return 0;
}
